#ifndef __QE_SPI_FLASH_H__
#define __QE_SPI_FLASH_H__



#include "qe_def.h"



#define FLASH_F_RESET                   	0x01
#define FLASH_F_4BYTE                  		0x02

#define QE_SPIF_CTRL_GET_CHIPINFO       	0x21
#define QE_SPIF_CTRL_BLOCK_ERASE       		0x22

#define QE_SPIF_CMD_PAGE_PROGRAM			0x02
#define QE_SPIF_CMD_READ_DATA				0x03
#define QE_SPIF_CMD_WRITE_DISABLE			0x04
#define QE_SPIF_CMD_READ_SR					0x05
#define QE_SPIF_CMD_WRITE_ENABLE			0x06
#define QE_SPIF_CMD_ENABLE_RESET			0x66
#define QE_SPIF_CMD_RESET					0x99
#define QE_SPIF_CMD_WORD_PROGRAM			0xAD
#define QE_SPIF_CMD_ENTER_4B_ADDRESS_MODE	0xB7
#define QE_SPIF_CMD_ERASE_CHIP				0xC7
#define QE_SPIF_CMD_EXIT_4B_ADDRESS_MODE	0xE9
#define QE_SPIF_CMD_JEDEC_ID				0x9F

/* Support manufacturer JEDEC ID */
#define JEDEC_ID_CYPRESS                    0x01
#define JEDEC_ID_FUJITSU                    0x04
#define JEDEC_ID_EON                        0x1C
#define JEDEC_ID_ATMEL                      0x1F
#define JEDEC_ID_MICRON                     0x20
#define JEDEC_ID_AMIC                       0x37
#define JEDEC_ID_SANYO                      0x62
#define JEDEC_ID_INTEL                      0x89
#define JEDEC_ID_ESMT                       0x8C
#define JEDEC_ID_FUDAN                      0xA1
#define JEDEC_ID_HYUNDAI                    0xAD
#define JEDEC_ID_SST                        0xBF
#define JEDEC_ID_MACRONIX                   0xC2
#define JEDEC_ID_GIGADEV                    0xC8
#define JEDEC_ID_ISSI                       0xD5
#define JEDEC_ID_WINBOND                    0xEF

/**
 * status register bits
 */
enum {
    QE_SPIF_SR_BUSY = (1 << 0), 		/**< busing */
    QE_SPIF_SR_WEL = (1 << 1),       	/**< write enable latch */
    QE_SPIF_SR_SRP = (1 << 7),      	/**< status register protect */
};

/**
 * flash program(write) data mode
 */
enum qe_spif_write_mode {
    QE_SPIF_WM_PAGE_256B = 1 << 0,                            /**< write 1 to 256 bytes per page */
    QE_SPIF_WM_BYTE = 1 << 1,                                 /**< byte write */
    QE_SPIF_WM_AAI = 1 << 2,                                  /**< auto address increment */
    QE_SPIF_WM_DUAL_BUFFER = 1 << 3,                          /**< dual-buffer write, like AT45DB series */
};

#define QE_SPIF_WM_BYTE_AAI		(QE_SPIF_WM_BYTE | QE_SPIF_WM_AAI)
#define QE_SPIF_WM_BYTE_DBF		(QE_SPIF_WM_BYTE | QE_SPIF_WM_DUAL_BUFFER)

typedef struct {
	char  *name;
	qe_u8  mf_id;
	qe_u8  mt_id;
	qe_u8  capacity_id;
	qe_u8  erase_sector_cmd;
	qe_u32 capacity;
	qe_u16 write_mode;
	qe_u8  flag;
    qe_u8  reserve;
	qe_u32 sector_size;
}qe_spif_chip;

typedef struct {
    qe_u32 addr;
    qe_u32 size;
    qe_u32 sector_size;
    qe_u8  erase_cmd;
    qe_u8  reserve[3]; 
}qe_spif_erase_message;

typedef struct qe_spif_device qe_spif_dev;

qe_size qe_spif_read(qe_spif_dev *flash, qe_u32 addr, qe_size size, qe_ptr buffer);

qe_ret qe_spif_write(qe_spif_dev *flash, qe_u32 addr, qe_size size, qe_const_ptr buffer);

qe_ret qe_spif_erase(qe_spif_dev *flash, qe_u32 addr, qe_size size);

qe_ret qe_spif_chip_erase(qe_spif_dev *flash);

qe_spif_dev *qe_spif_find(const char *name);
qe_spif_dev *qe_spif_probe(const char *sf_name, const char *spi_name, qe_spif_chip *match);

#endif /* qe_spiflash_t */

